package com.ruoyi.common.mqtts;


import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.redis.RedisCache;
import com.ruoyi.common.redis.RedisConst;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.project.stop.domain.*;
import com.ruoyi.project.stop.service.*;
import com.ruoyi.project.system.dict.service.IDictTypeService;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttMessage;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;


/**
 * 常规MQTT回调函数
 *
 */
@Slf4j
public class MqttClientCallback implements MqttCallback {

    /**
     * 系统的mqtt客户端id
     */
    private String mqttClientId;

    public MqttClientCallback(String mqttClientId) {
        this.mqttClientId = mqttClientId;
    }
    /**
     * MQTT 断开连接会执行此方法
     */
    @Override
    public void connectionLost(Throwable throwable) {
        log.info("断开了MQTT连接 ：{}", throwable.getMessage());
        //log.error(throwable.getMessage(), throwable);
    }

    /**
     * publish发布成功后会执行到这里
     */
    @Override
    public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
        log.info("发布消息成功");
    }

    /**
     * subscribe订阅后得到的消息会执行到这里
     */
    @Override
    public void messageArrived(String topic, MqttMessage message) throws Exception {
        //  TODO    此处可以将订阅得到的消息进行业务处理、数据存储
        log.info("收到来自 " + mqttClientId + "====" + topic + " 的消息：{}", new String(message.getPayload()));

        if("sensorRecordTest".equals(topic)){
            sensorRecordTestVoid(new String(message.getPayload()));
        }
    }

    private void sensorRecordTestVoid(String message) {
        /* 每5s推送一次传感器数据 之后入库 * */
        try {
            JSONObject senjorJson = JSONObject.parseObject(message);
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            // 初始化返回数据
            String temperatureOne = String.valueOf(senjorJson.get("temperatureOne"));
            String temperatureSecond = String.valueOf(senjorJson.get("temperatureSecond"));
            String temperatureThird = String.valueOf(senjorJson.get("temperatureThird"));
            String temperatureFour = String.valueOf(senjorJson.get("temperatureFour"));
            String pressureOne = String.valueOf(senjorJson.get("pressureOne"));
            String pressureSecond = String.valueOf(senjorJson.get("pressureSecond"));
            String pressureThird = String.valueOf(senjorJson.get("pressureThird"));
            String pressureFour = String.valueOf(senjorJson.get("pressureFour"));
            System.out.println(senjorJson);
            //发送心跳数据到mqtt
            // 获取客户端实例
            ConcurrentHashMap<String, MqttClientConnect> mqttClients = MqttClientConnect.mqttClients;
            MqttClientConnect mqttClientConnect = mqttClients.get("1");
            String heartTopic = "sensorRecord";
            mqttClientConnect.pub(heartTopic, senjorJson.toJSONString());

            BigDecimal temperatureOneBig = BigDecimal.valueOf(Double.valueOf(temperatureOne));
            BigDecimal temperatureSecondBig = BigDecimal.valueOf(Double.valueOf(temperatureSecond));
            BigDecimal temperatureThirdBig = BigDecimal.valueOf(Double.valueOf(temperatureThird));
            BigDecimal temperatureFourBig = BigDecimal.valueOf(Double.valueOf(temperatureFour));
            BigDecimal pressureOneBig = BigDecimal.valueOf(Double.valueOf(pressureOne));
            BigDecimal pressureSecondBig = BigDecimal.valueOf(Double.valueOf(pressureSecond));
            BigDecimal pressureThirdBig = BigDecimal.valueOf(Double.valueOf(pressureThird));
            BigDecimal pressureFourBig = BigDecimal.valueOf(Double.valueOf(pressureFour));
            /**
             * 查询 —— 最新船舶信息数据（redis）
             * 插入 —— 传感器存入数据库*/
            IShipRecordService shipRecordService = SpringUtils.getBean(IShipRecordService.class);
            ISensorRecordService sensorRecordService = SpringUtils.getBean(ISensorRecordService.class);
            ShipRecord shipRecord = shipRecordService.selectShipRecordByIdLast();
            SensorRecord sensorRecord = new SensorRecord();
            sensorRecord.setShipId(shipRecord.getId());
            sensorRecord.setTemperatureOne(temperatureOneBig);
            sensorRecord.setTemperatureSecond(temperatureSecondBig);
            sensorRecord.setTemperatureThird(temperatureThirdBig);
            sensorRecord.setTemperatureFour(temperatureFourBig);
            sensorRecord.setPressureOne(pressureOneBig);
            sensorRecord.setPressureSecond(pressureSecondBig);
            sensorRecord.setPressureThird(pressureThirdBig);
            sensorRecord.setPressureFour(pressureFourBig);
            sensorRecord.setCreateTime(simpleDateFormat.parse(String.valueOf(senjorJson.get("cdate"))));
            sensorRecordService.insertSensorRecord(sensorRecord);

            /**
             * 查询 —— 最新报警阈值设置（redis）
             * 插入 —— 历史报警记录存入数据库*/
            this.earlyWarning(shipRecord.getId(), shipRecord.getShipName(), temperatureOneBig, temperatureSecondBig, temperatureThirdBig, temperatureFourBig
                    , pressureOneBig, pressureSecondBig, pressureThirdBig, pressureFourBig, mqttClientConnect);


        }catch (Exception e){
            e.printStackTrace();
        }
    }
    public void earlyWarning(Long shipId, String shipName, BigDecimal temperatureOne, BigDecimal temperatureSecond, BigDecimal temperatureThird, BigDecimal temperatureFour
            , BigDecimal pressureOne, BigDecimal pressureSecond, BigDecimal pressureThird, BigDecimal pressureFour, MqttClientConnect mqttClientConnect){
        try{
            /*首先判断有无数据超出异常*/
            // 获取报警阈值 设置值
            IWarnConfigService warnConfigService = SpringUtils.getBean(IWarnConfigService.class);
            WarnConfig warnConfig = warnConfigService.selectWarnConfigById(1L);
            BigDecimal preMax = warnConfig.getPressureMax();
            BigDecimal preMaxSecond = warnConfig.getPressureMaxSecond();
            //BigDecimal tepMax = warnConfig.getTemperatureMax();
            if(pressureOne.compareTo(preMax) >=0 || pressureSecond.compareTo(preMax) >=0 || pressureThird.compareTo(preMax) >=0 || pressureFour.compareTo(preMax) >=0){
                /* 有数据超出阈值 */
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Long warnType = 0L;
                Long armNum = 0L;
                BigDecimal warnNum = new BigDecimal(0);
                String warnDetail = "";
                // 比较是否有报警数据
                if(pressureOne.compareTo(preMax) >=0){
                    warnType = 5L;
                    armNum = 1L;
                    warnNum = pressureOne;
                    warnDetail = "18Z1压强过高：" + pressureOne + "MPa, "  + simpleDateFormat.format(new Date()) + shipName + " 船 ";
                    this.saveWarnHistoryByTcp(shipId, warnType, armNum, warnNum, warnDetail);
                }
                if(pressureSecond.compareTo(preMax) >=0){
                    warnType = 5L;
                    armNum = 2L;
                    warnNum = pressureSecond;
                    warnDetail = "18Z2压强过高：" + pressureSecond + "MPa, "  + simpleDateFormat.format(new Date()) + shipName + " 船 ";
                    this.saveWarnHistoryByTcp(shipId, warnType, armNum, warnNum, warnDetail);
                }
                if(pressureThird.compareTo(preMax) >=0){
                    warnType = 5L;
                    armNum = 3L;
                    warnNum = pressureThird;
                    warnDetail = "18Z3压强过高：" + pressureThird + "MPa, "  + simpleDateFormat.format(new Date()) + shipName + " 船 ";
                    this.saveWarnHistoryByTcp(shipId, warnType, armNum, warnNum, warnDetail);
                }
                if(pressureFour.compareTo(preMax) >=0){
                    warnType = 5L;
                    armNum = 4L;
                    warnNum = pressureFour;
                    warnDetail = "18Z4压强过高：" + pressureFour + "MPa, "  + simpleDateFormat.format(new Date()) + shipName + " 船 ";
                    this.saveWarnHistoryByTcp(shipId, warnType, armNum, warnNum, warnDetail);
                }
            }
            /*自动拍停按钮打开 压力大于二级 连续三次，报警并执行自动拍停指令*/
            IDictTypeService dictTypeService = SpringUtils.getBean(IDictTypeService.class);
            Long autoStatus = dictTypeService.getDictTypeByAutoStop();
            if(autoStatus == 0L){
                if(pressureOne.compareTo(preMaxSecond) >=0 || pressureSecond.compareTo(preMaxSecond) >=0 || pressureThird.compareTo(preMaxSecond) >=0 || pressureFour.compareTo(preMaxSecond) >=0){
                    RedisCache redisCache = SpringUtils.getBean(RedisCache.class);
                    Integer warnSecondNum = 0;
                    String warnSecondNumStr =  JSON.toJSONString(redisCache.getCacheObject(RedisConst.WARN_SECOND_NUM));
                    if(ObjectUtil.isNotEmpty(warnSecondNumStr) &&  !"null".equals(warnSecondNumStr)){
                        warnSecondNum = Integer.valueOf(warnSecondNumStr);
                        warnSecondNum = warnSecondNum + 1;
                    }else {
                        warnSecondNum = warnSecondNum + 1;
                    }
                    // 判断是否连续报警3次
                    if(warnSecondNum >=3){
                        warnSecondNum = 0;
                        /*触发自动拍停*/
                        mqttClientConnect.pub("autoStop","autoStop");
                    }
                    redisCache.setCacheObject(RedisConst.WARN_SECOND_NUM, warnSecondNum, 3, TimeUnit.SECONDS);
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public void saveWarnHistoryByTcp(Long shipId, Long warnType, Long armNum, BigDecimal warnNum, String warnDetail){
        try {
            // 初始化预警记录实列
            WarnHistory warnHistory = new WarnHistory();
            IWarnHistoryService warnHistoryService = SpringUtils.getBean(IWarnHistoryService.class);
            warnHistory.setWarnDel(0L);
            warnHistory.setShipId(shipId);
            warnHistory.setWarnType(warnType);
            warnHistory.setArmNum(armNum);
            warnHistory.setWarnNum(warnNum);
            warnHistory.setWarnDetail(warnDetail);
            warnHistory.setCreateTime(new Date());
            warnHistoryService.insertWarnHistory(warnHistory);
            /* 如果是异常报警 需要存储急停按钮为 已激活状态 */
            IStopRecordService stopRecordService = SpringUtils.getBean(IStopRecordService.class);
            StopRecordVO stopRecordVO = new StopRecordVO();
            stopRecordVO.setShipId(shipId);
            stopRecordVO.setStopType(0L);
            stopRecordVO.setStopStatus(5L);
            stopRecordVO.setCreateTime(new Date());
            stopRecordService.insertStopRecord(stopRecordVO);
            /* 发送报警数据到mqtt */
            // 获取客户端实例
            ConcurrentHashMap<String, MqttClientConnect> mqttClients = MqttClientConnect.mqttClients;
            MqttClientConnect mqttClientConnect = mqttClients.get("1");
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            JSONObject warnJson = new JSONObject();
            warnJson.put("cdate", simpleDateFormat.format(new Date()));
            warnJson.put("shipId", shipId);
            warnJson.put("warnType",  warnType);
            warnJson.put("armNum",  armNum);
            warnJson.put("warnNum",  warnNum);
            warnJson.put("warnDetail",  warnDetail);
            mqttClientConnect.pub("warnRecord", warnJson.toJSONString());
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        // 初始化返回数据
        // 初始化返回数据
        DecimalFormat df1 = new DecimalFormat("0.0");
        DecimalFormat df2 = new DecimalFormat("0.00");
        JSONObject json = new JSONObject();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        json.put("cdate", simpleDateFormat.format(new Date()));
        String temperatureOne = df1.format(BigDecimal.valueOf(Math.random()*63));
        String temperatureSecond = df1.format(BigDecimal.valueOf(Math.random()*63));
        String temperatureThird = df1.format(BigDecimal.valueOf(Math.random()*63));
        String temperatureFour = df1.format(BigDecimal.valueOf(Math.random()*63));

        String pressureOne = df2.format(BigDecimal.valueOf(Math.random() * 0.93));
        String pressureSecond = df2.format(BigDecimal.valueOf(Math.random() * 0.93));
        String pressureThird = df2.format(BigDecimal.valueOf(Math.random() * 0.93));
        String pressureFour = df2.format(BigDecimal.valueOf(Math.random() * 0.93));



        BigDecimal temperatureOneBig = BigDecimal.valueOf(Double.valueOf(temperatureOne));
        BigDecimal temperatureSecondBig = BigDecimal.valueOf(Double.valueOf(temperatureSecond));
        BigDecimal temperatureThirdBig = BigDecimal.valueOf(Double.valueOf(temperatureThird));
        BigDecimal temperatureFourBig = BigDecimal.valueOf(Double.valueOf(temperatureFour));
        BigDecimal pressureOneBig = BigDecimal.valueOf(Double.valueOf(pressureOne));
        BigDecimal pressureSecondBig = BigDecimal.valueOf(Double.valueOf(pressureSecond));
        BigDecimal pressureThirdBig = BigDecimal.valueOf(Double.valueOf(pressureThird));
        BigDecimal pressureFourBig = BigDecimal.valueOf(Double.valueOf(pressureFour));

        json.put("temperatureOne", temperatureOneBig);
        json.put("temperatureSecond",  temperatureSecondBig);
        json.put("temperatureThird",  temperatureThirdBig);
        json.put("temperatureFour",  temperatureFourBig);
        json.put("pressureOne",  pressureOneBig);
        json.put("pressureSecond", pressureSecondBig);
        json.put("pressureThird",  pressureThirdBig);
        json.put("pressureFour",  pressureFourBig);

        System.out.println(json);
    }

}
